/**
  ETFDAQ Project
  \class TAController
  \brief A VME controller. Supposed to be a virtual class
  \author SUN Yazhou, asia.rabbit@163.com
  \since 2024-08-12
  \date 2024-08-12 last modified

  \copyright Copyright (c) 2024 IMP-CAS with LGPLv3 LICENSE
*/

#ifndef TAController_h
#define TAController_h

#include <string>
#include <cstdint>
#include <signal.h>

class TAYaml;

using std::string;

class TAController{
public:
  TAController(const string &dev);
  virtual ~TAController();

  const char *GetName() const{ return fName.data(); }
  virtual void Initialize();
  virtual void Reset() = 0;
  void SetConfig(const TAYaml *c){ fConfig = c; }
  ///--- processing interrupts ---///
  /// \param mask: irq levels(1~7,3=1<<3), 0xFE: all 1~7 irq levels are enabled
  virtual void EnableIRQ(int mask = 0xFE) = 0; ///< enable interrupt w.r.t. mask
  virtual void DisableIRQ() = 0; ///< disable all the interrupt
  virtual void PrintIRQStatus() = 0; ///< show the IRQ register
  virtual void GetIRQ() const = 0; ///< fetch and show interrupt status
  virtual void SuspendForIRQ(); ///< wait for interrupts
  virtual bool IsIRQed() const; ///< whether an IRQ has arrived

  static void printsig(sigset_t &s);

  ///--- the daq loop ---///
  virtual void DropDead() = 0; ///< set ch_out to forbit the trigger
  virtual void Resurrect() = 0; ///< clear the set ch_out

  ///--- read and write the control registers ---///
  virtual void CtrlReadD32(int addr) = 0;
  virtual void CtrlWriteD32(int addr, uint32_t data) = 0; ///< val |= data

  ///--- read and write data via VME bus ---///
  virtual uint32_t A32D32Read(uint32_t addr) = 0;
  virtual uint16_t A32D16Read(uint32_t addr) = 0;
  virtual void A32D32Write(uint32_t addr, uint32_t data) = 0;
  virtual void A32D16Write(uint32_t addr, uint16_t data) = 0;
  /// \retval nof words read \param nreq: requested nof words to be read
  virtual int A32BLT32Read(uint32_t addr, uint32_t *data, uint32_t nreq) = 0;
  /// \retval nof words read \param nreq: requested nof words to be read
  virtual int A32MBLT64Read(uint32_t addr, uint32_t *data, uint32_t nreq) = 0;

  /// print functions ///
  void PrintD32InBinaryForm() const; ///< print fD32 in binary form
  void PrintD16InBinaryForm() const; ///< print fD16 in binary form
  uint32_t D32Data() const{ return fD32; }
  uint16_t D16Data() const{ return fD16; }

protected:
  string fName;
  int fd; ///< the file descriptor of the opened sis3100
  uint32_t fD32;
  uint16_t fD16;
  int fExtraDeadTime; ///< in us
  const TAYaml *fConfig; ///< the user input

  /// to set the sig mask set for *this* process
  const int fTargetSIG; //< signal used to signify an IRQ
  sigset_t fSigMask, fOldSigMask;
  struct sigaction fSigAction, fOldSigAction; ///< to capture the IRQ signal
};

#endif
